home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / language / asxsrc.arc / ASEXPR.C < prev    next >
C/C++ Source or Header  |  1991-06-10  |  6KB  |  330 lines

  1. /* asexpr.c */
  2.  
  3. /*
  4.  * (C) Copyright 1989
  5.  * All Rights Reserved
  6.  *
  7.  * Alan R. Baldwin
  8.  * 721 Berkeley St.
  9.  * Kent, Ohio  44240
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include <setjmp.h>
  14. #include "asm.h"
  15.  
  16. /*
  17.  * Read an expression. The value of the
  18.  * expression and its associated relocation
  19.  * information is stored into the `expr'
  20.  * structure supplied by the user. `N' is
  21.  * a firewall priority; all top level calls
  22.  * (from the user) should be made with `n'
  23.  * set to 0.
  24.  */
  25. VOID
  26. expr(esp, n)
  27. register struct expr *esp;
  28. {
  29.     register c, d, p;
  30.     struct area *ap;
  31.     struct expr re;
  32.  
  33.     term(esp);
  34.     while (ctype[c = getnb()] == BINOP) {
  35.         if ((p = oprio(c)) <= n)
  36.             break;
  37.         if ((c == '>' || c == '<') && c != get())
  38.             qerr();
  39.         expr(&re, p);
  40.         if (c == '+') {
  41.             if (esp->e_base.e_ap == NULL) {
  42.                 esp->e_flag = re.e_flag;
  43.                 esp->e_base.e_ap = re.e_base.e_ap;
  44.             } else
  45.             if (re.e_base.e_ap) {
  46.                 rerr();
  47.             }
  48.             esp->e_addr += re.e_addr;
  49.         } else
  50.         if (c == '-') {
  51.             if (ap = re.e_base.e_ap) {
  52.                 if (esp->e_base.e_ap == ap) {
  53.                     esp->e_base.e_ap = NULL;
  54.                 } else {
  55.                     rerr();
  56.                 }
  57.                 if (esp->e_flag || re.e_flag) {
  58.                     rerr();
  59.                 }
  60.             }
  61.             esp->e_addr -= re.e_addr;
  62.         } else {
  63.             abscheck(esp);
  64.             abscheck(&re);
  65.             switch (c) {
  66.  
  67.             case '*':
  68.                 esp->e_addr *= re.e_addr;
  69.                 break;
  70.  
  71.             case '/':
  72.                 esp->e_addr /= re.e_addr;
  73.                 break;
  74.  
  75.             case '&':
  76.                 esp->e_addr &= re.e_addr;
  77.                 break;
  78.  
  79.             case '|':
  80.                 esp->e_addr |= re.e_addr;
  81.                 break;
  82.  
  83.             case '%':
  84.                 esp->e_addr %= re.e_addr;
  85.                 break;
  86.  
  87.             case '^':
  88.                 esp->e_addr ^= re.e_addr;
  89.                 break;
  90.  
  91.             case '<':
  92.                 esp->e_addr <<= re.e_addr;
  93.                 break;
  94.  
  95.             case '>':
  96.                 esp->e_addr >>= re.e_addr;
  97.                 break;
  98.             }
  99.         }
  100.     }
  101.     unget(c);
  102. }
  103.  
  104. /*
  105.  * Read an absolute expression.
  106.  */
  107. addr_t
  108. absexpr()
  109. {
  110.     struct expr e;
  111.  
  112.     expr(&e, 0);
  113.     abscheck(&e);
  114.     return (e.e_addr);
  115. }
  116.  
  117. /*
  118.  * Read a term.
  119.  * Handles unary operators, brackets,
  120.  * constants in decimal, octal or hexadecimal
  121.  * and identifiers. This routine is also
  122.  * responsible for setting the relocation type
  123.  * to symbol based (e.flag != 0) on global
  124.  * references.
  125.  */
  126. VOID
  127. term(esp)
  128. register struct expr *esp;
  129. {
  130.     register c, n, nd;
  131.     char id[NCPS];
  132.     struct sym  *sp;
  133.     struct tsym *tp;
  134.     int r, v;
  135.  
  136.     c = getnb();
  137.     if (c == '#') { c = getnb(); }
  138.     if (c == LFTERM) {
  139.         expr(esp, 0);
  140.         if (getnb() != RTTERM)
  141.             qerr();
  142.         return;
  143.     }
  144.     if (c == '-') {
  145.         expr(esp, 100);
  146.         abscheck(esp);
  147.         esp->e_addr = -esp->e_addr;
  148.         return;
  149.     }
  150.     if (c == '~') {
  151.         expr(esp, 100);
  152.         abscheck(esp);
  153.         esp->e_addr = ~esp->e_addr;
  154.         return;
  155.     }
  156.     if (c == '\'') {
  157.         esp->e_mode = S_USER;
  158.         esp->e_flag = 0;
  159.         esp->e_base.e_ap = NULL;
  160.         esp->e_addr = getmap(-1);
  161.         return;
  162.     }
  163.     if (c == '\"') {
  164.         esp->e_mode = S_USER;
  165.         esp->e_flag = 0;
  166.         esp->e_base.e_ap = NULL;
  167.         if (hilo) {
  168.             esp->e_addr = (getmap(-1)&0377)<<8 | (getmap(-1)&0377);
  169.         } else {
  170.             esp->e_addr = (getmap(-1)&0377) | (getmap(-1)&0377)<<8;
  171.         }
  172.         return;
  173.     }
  174.     if (c == '>' || c == '<') {
  175.         expr(esp, 100);
  176.         abscheck(esp);
  177.         if (c == '>')
  178.             esp->e_addr >>= 8;
  179.         esp->e_addr &= 0377;
  180.         return;
  181.     }
  182.     if (ctype[c] == DIGIT) {
  183.         esp->e_mode = S_USER;
  184.         esp->e_flag = 0;
  185.         esp->e_base.e_ap = NULL;
  186.         r = radix;
  187.         if (c == '0') {
  188.             c = get();
  189.             switch (c) {
  190.             case 'b':
  191.             case 'B':
  192.                 r = 2;
  193.                 c = get();
  194.                 break;
  195.             case '@':
  196.             case 'o':
  197.             case 'O':
  198.             case 'q':
  199.             case 'Q':
  200.                 r = 8;
  201.                 c = get();
  202.                 break;
  203.             case 'd':
  204.             case 'D':
  205.                 r = 10;
  206.                 c = get();
  207.                 break;
  208.             case 'h':
  209.             case 'H':
  210.             case 'x':
  211.             case 'X':
  212.                 r = 16;
  213.                 c = get();
  214.                 break;
  215.             default:
  216.                 break;
  217.             }
  218.         }
  219.         n = 0;
  220.         nd = 0;
  221.         while ((v = digit(c, r)) >= 0) {
  222.             n = r*n + v;
  223.             nd = 10*nd + v;
  224.             c = get();
  225.         }
  226.         if (c=='$') {
  227.             tp = symp->s_tsym;
  228.             while (tp) {
  229.                 if (nd == tp->t_num) {
  230.                     esp->e_base.e_ap = tp->t_area;
  231.                     esp->e_addr = tp->t_addr;
  232.                     return;
  233.                 }
  234.                 tp = tp->t_lnk;
  235.             }
  236.             err('u');
  237.             esp->e_addr = 0;
  238.             return;
  239.         }
  240.         unget(c);
  241.         esp->e_addr = n;
  242.         return;
  243.     }
  244.     if (ctype[c] == LETTER) {
  245.         esp->e_mode = S_USER;
  246.         esp->e_flag = 0;
  247.         esp->e_base.e_ap = NULL;
  248.         esp->e_addr = 0;
  249.         getid(id, c);
  250.         if (sp = lookup(id)) {
  251.             if (sp->s_type == S_NEW) {
  252.                 if (sp->s_flag&S_GBL) {
  253.                     esp->e_flag = 1;
  254.                     esp->e_base.e_sp = sp;
  255.                     return;
  256.                 }
  257.                 err('u');
  258.                 return;
  259.             }
  260.             esp->e_mode = sp->s_type;
  261.             esp->e_base.e_ap = sp->s_area;
  262.             esp->e_addr = sp->s_addr;
  263.             return;
  264.         }
  265.         err('u');
  266.         return;
  267.     }
  268.     qerr();
  269. }
  270.  
  271. /*
  272.  * If `c' is a legal radix `r' digit
  273.  * return its value; otherwise return
  274.  * -1.
  275.  */
  276. int
  277. digit(c, r)
  278. register c, r;
  279. {
  280.     if (r == 16) {
  281.         if (c >= 'A' && c <= 'F')
  282.             return (c - 'A' + 10);
  283.         if (c >= 'a' && c <= 'f')
  284.             return (c - 'a' + 10);
  285.     }
  286.     if (c >= '0' && c <= '9')
  287.         return (c - '0');
  288.     return (-1);
  289. }
  290.  
  291. /*
  292.  * Check if the value of the supplied
  293.  * expression is absolute; if not give
  294.  * a relocation error and force the
  295.  * type to absolute.
  296.  */
  297. VOID
  298. abscheck(esp)
  299. register struct expr *esp;
  300. {
  301.     if (esp->e_flag || esp->e_base.e_ap) {
  302.         rerr();
  303.         esp->e_flag = 0;
  304.         esp->e_base.e_ap = NULL;
  305.     }
  306. }
  307.  
  308. /*
  309.  * Return the priority of the binary
  310.  * operator `c'.
  311.  */
  312. int
  313. oprio(c)
  314. register c;
  315. {
  316.     if (c == '*' || c == '/' || c == '%')
  317.         return (10);
  318.     if (c == '+' || c == '-')
  319.         return (7);
  320.     if (c == '<' || c == '>')
  321.         return (5);
  322.     if (c == '^')
  323.         return (4);
  324.     if (c == '&')
  325.         return (3);
  326.     if (c == '|')
  327.         return (1);
  328.     return (0);
  329. }
  330.